R Sienna example:

rm(list = ls())

fpackage.check <- function(packages) {
    lapply(packages, FUN = function(x) {
        if (!require(x, character.only = TRUE)) {
            install.packages(x, dependencies = TRUE)
            library(x, character.only = TRUE)
        }
    })
}

fsave <- function(x, file = NULL, location = "./data/processed/") {
    ifelse(!dir.exists("data"), dir.create("data"), FALSE)
    ifelse(!dir.exists("data/processed"), dir.create("data/processed"), FALSE)
    if (is.null(file))
        file = deparse(substitute(x))
    datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
    totalname <- paste(location, datename, file, ".rda", sep = "")
    save(x, file = totalname)  #need to fix if file is reloaded as input name, not as x. 
}

fload <- function(filename) {
    load(filename)
    get(ls()[ls() != "filename"])
}

fshowdf <- function(x, ...) {
    knitr::kable(x, digits = 2, "html", ...) %>%
        kableExtra::kable_styling(bootstrap_options = c("striped", "hover")) %>%
        kableExtra::scroll_box(width = "100%", height = "300px")
}

colorize <- function(x, color) {
    sprintf("<span style='color: %s;'>%s</span>", color, x)
}
fpackage.check(packages)
[[1]]
NULL

NEED DATA - use build in datasets from RSIENNA ?s501 Is adjacency matrix for network type 1. Goal: Follow steps in 7.1 for different data:

Step 1. Define data

Dependent variable: ties

s502 #network at timepoint 2
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34
1   0  0  0  0  0  0  0  0  0   1   0   0   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0
2   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0
3   0  0  0  1  0  0  0  0  1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
4   0  0  1  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
5   0  0  0  1  0  0  0  0  0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
6   0  0  0  0  0  0  0  1  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
7   0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
8   0  0  0  0  0  1  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
9   0  0  1  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
10  1  0  0  0  0  0  0  0  0   0   1   0   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0
11  1  0  0  0  0  0  0  0  0   1   0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   1   0   0   0   1   0   0   0   0
12  0  0  0  0  0  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0
13  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
14  1  0  0  0  0  0  0  0  0   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
15  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
16  0  0  0  0  0  0  0  0  0   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0
17  0  0  0  1  1  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   1   0   1   0   0   0   0   0   0   0   1   0   0
18  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
19  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   0   0   0   0
20  0  0  0  0  0  0  0  0  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50
1    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
3    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
4    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
5    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
6    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
7    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
8    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
9    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
10   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
11   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
12   0   0   0   0   0   0   0   1   0   1   0   0   0   0   0   0
13   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
14   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
15   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0
16   0   0   0   0   0   0   0   1   0   0   0   0   0   0   0   0
17   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
18   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
19   0   1   0   0   0   0   1   0   0   0   0   0   0   0   0   0
20   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
 [ reached 'max' / getOption("max.print") -- omitted 30 rows ]

Inspect networks. Remove NAs, make sure diagonal. Need to see binary (not weighted)

Put networks in an array

c(dim(s501),2)
[1] 50 50  2

could replace this with data set from last week

Define dependent - and independent - variable

 # don't need wave 2 - just modeling at independent variable, influencing all ministeps between time 1 and time 2 
alcohol 
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 
 3  2  2  2  3  4  4  4  2  4  5  5  3  3  4  4  2  4  3  2  1  3  4  3  3  4  2  2  3  1  4  4  3  2  3  4  2  3  2  1  4  4  2  5 
45 46 47 48 49 50 
 2  2  2  2  1  1 

Now combine into dataset - if use Rsiena, need this.

myeff
  effectName               include fix   test  initialValue parm
1 basic rate parameter net TRUE    FALSE FALSE    4.69604   0   
2 outdegree (density)      TRUE    FALSE FALSE   -1.48852   0   
3 reciprocity              TRUE    FALSE FALSE    0.00000   0   

Now can look at myeff - look at starting values - has density of two networks, reciprocity

Want much more statistics for model, though!!

Step 2:

Can see all effects that could include in the dataset. Which is a lot. And this is a simple dataset. and yeah, its huge. Also can see that the type depends on weight function (evaluation (), endowment (), and creation ())

Example. Jochem wants to make tie with Jos. Jochem’s consideration to make a tie with Jos could be different than consideration to maintain a tie, could be different that decistions to break a tie. Can’t estimate all three. Evalution: mechanisms the same for making as breaking, endowment = maintaining, creation = if there are none then what is the cost.

In this course: just use evaluation function. Assume mechanisms and functions to make/break ties are similar. include degree for evaluation. But what are all these effects? - should be able to calculate statistic for each effect for an ego in a network… Mathematical formula in chapter 12.

effectsDocumentation(myeff)
Effects documentation written to file myeff.html .

Make sure to understand out degree and reciprocity effects - statistics - will play around with this next week. Need to think of theory for which statistics are relevant. - Look at literature for statistics, think about it, play and see if effects exists - how work in reality? propose idea, write notation, see if effect exists in manual, etc. Lots of notation because everyone is looking for their own effects. - need to include more effects if what to.

Step 3: Look at intial data

print01Report(mydata)

# gives initial description of data 
# reading network variables , covariates, density measures/changes in networks, tie changes between subsequent observations... calculate how much networks changed over time. 
# dont use balance calculation 

Step 4: Add effects

myeff <- includeEffects(myeff, isolateNet, inPop, outAct)
  effectNumber effectName            shortName  include fix   test  initialValue parm
1  78          indegree - popularity inPop      TRUE    FALSE FALSE          0   0   
2 106          outdegree - activity  outAct     TRUE    FALSE FALSE          0   0   
3 149          network-isolate       isolateNet TRUE    FALSE FALSE          0   0   

outAct - look at the number of times I have and square that: especially the people that have a lot of ties will send a lot of ties. - evaluation function of tie1 0 ties, and tie1 4 ties - then at t2 people who have ties are more likely to send more ties

We know tie distributions are skewed, some people send a lot of ties and others dont.

inPop: in degree activity: people who reseive a lot of in-degrees send a lot of out-degrees

isolateNet: people without a lot of indegree nets.

Can see that starting values are 0 – hypothesis testing

Step 5: Estimation

ansM1
Estimates, standard errors and convergence t-ratios

                                Estimate   Standard   Convergence 
                                             Error      t-ratio   

Rate parameters: 
  0       Rate parameter         5.6461  ( 0.8889   )             

Other parameters: 
  1. eval outdegree (density)   -2.1186  ( 0.4326   )   -0.0337   
  2. eval reciprocity            2.4448  ( 0.2376   )   -0.0049   
  3. eval indegree - popularity  0.0724  ( 0.0638   )   -0.0378   
  4. eval outdegree - activity  -0.0645  ( 0.0676   )   -0.0412   
  5. eval network-isolate        1.7737  ( 2.2226   )   -0.0120   

Overall maximum convergence ratio:    0.0684 


Total of 2203 iteration steps.

Now have first estimated Rsiena model!

if significant: more indegrees- more likely to send later. people with more out-degrees - more likely to send less (negative). isolate more likely to be alone.

Need to think of model that makes sense in this

REVIEWING RSIENA NOW - negative degree - density is less than .5 - interpretations - Mailing list for TOM

Afternoon: play with estimating our own models Nice to do with our own data - collaboration networks. Logic of RSIENA: took actor oriented approach - works if ties are directed. if undirected network, logic is different: the actor deciding on undirected tie is difficult. Advise: for now treat as undirected - and then evaluate tie. undirected tie by reach consensus, forced into concensus, etc - reciprocity matters less now.

Now play with it

Now - referencing web scraping site

fcolnet <- function(data = scholars, university = "RU", discipline = "sociology", waves = list(c(2015,
    2018), c(2019, 2023)), type = c("first")) {

    # step 1
    demographics <- do.call(rbind.data.frame, data$demographics)
    demographics <- demographics %>%
        mutate(Universiteit1.22 = replace(Universiteit1.22, is.na(Universiteit1.22), ""), Universiteit2.22 = replace(Universiteit2.22,
            is.na(Universiteit2.22), ""), Universiteit1.24 = replace(Universiteit1.24, is.na(Universiteit1.24),
            ""), Universiteit2.24 = replace(Universiteit2.24, is.na(Universiteit2.24), ""), discipline.22 = replace(discipline.22,
            is.na(discipline.22), ""), discipline.24 = replace(discipline.24, is.na(discipline.24), ""))

    sample <- which((demographics$Universiteit1.22 %in% university | demographics$Universiteit2.22 %in%
        university | demographics$Universiteit1.24 %in% university | demographics$Universiteit2.24 %in%
        university) & (demographics$discipline.22 %in% discipline | demographics$discipline.24 %in% discipline))

    demographics_soc <- demographics[sample, ]
    scholars_sel <- lapply(scholars, "[", sample)

    # step 2
    ids <- demographics_soc$au_id
    nwaves <- length(waves)
    nets <- array(0, dim = c(nwaves, length(ids), length(ids)), dimnames = list(wave = 1:nwaves, ids,
        ids))
    dimnames(nets)

    # step 3
    df_works <- tibble(works_id = unlist(lapply(scholars_sel$work, function(l) l$id)), works_author = unlist(lapply(scholars_sel$work,
        function(l) l$author), recursive = FALSE), works_year = unlist(lapply(scholars_sel$work, function(l) l$publication_year),
        recursive = FALSE))

    df_works <- df_works[!duplicated(df_works), ]

    # step 4
    if (type == "first") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                ego <- df_works_w$works_author[i][[1]]$au_id[1]
                alters <- df_works_w$works_author[i][[1]]$au_id[-1]
                if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
                  nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
                }
            }
        }
    }

    if (type == "last") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                ego <- rev(df_works_w$works_author[i][[1]]$au_id)[1]
                alters <- rev(df_works_w$works_author[i][[1]]$au_id)[-1]
                if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
                  nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
                }
            }
        }
    }

    if (type == "all") {
        for (j in 1:nwaves) {
            df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
                ]
            for (i in 1:nrow(df_works_w)) {
                egos <- df_works_w$works_author[i][[1]]$au_id
                if (sum(ids %in% egos) > 0) {
                  nets[j, which(ids %in% egos), which(ids %in% egos)] <- 1
                }
            }
        }
    }
    output <- list()
    output$data <- scholars_sel
    output$nets <- nets
    return(output)
}

Example in class from 10 October Siena dependent variable

answer_ex
Estimates, standard errors and convergence t-ratios

                                           Estimate   Standard   Convergence 
                                                        Error      t-ratio   
Network Dynamics 
   1. rate constant mynet1 rate (period 1)  5.7880  ( 0.9880   )    0.0777   
   2. rate constant mynet1 rate (period 2)  4.5365  ( 0.6468   )   -0.0510   
   3. eval outdegree (density)             -1.9196  ( 0.2519   )    0.0175   
   4. eval reciprocity                      2.7951  ( 0.1876   )   -0.0070   
   5. eval unequal mybeh                   -0.4987  ( 0.3490   )    0.0032   
   6. eval unequal smoke                   -0.1958  ( 0.1405   )   -0.0074   

Behavior Dynamics
   7. rate rate mybeh (period 1)            1.2022  ( 0.3140   )    0.0557   
   8. rate rate mybeh (period 2)            1.6729  ( 0.4611   )    0.0577   
   9. eval mybeh linear shape               0.3601  ( 0.1454   )    0.0118   
  10. eval mybeh quadratic shape           -0.1961  ( 0.0906   )    0.0197   

Overall maximum convergence ratio:    0.1356 


Total of 2926 iteration steps.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFIgU2llbm5hIGV4YW1wbGU6IA0KDQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKCkpDQoNCmZwYWNrYWdlLmNoZWNrIDwtIGZ1bmN0aW9uKHBhY2thZ2VzKSB7DQogICAgbGFwcGx5KHBhY2thZ2VzLCBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgICAgIGlmICghcmVxdWlyZSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQogICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKHgsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICAgICAgICAgICBsaWJyYXJ5KHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiAgICAgICAgfQ0KICAgIH0pDQp9DQoNCmZzYXZlIDwtIGZ1bmN0aW9uKHgsIGZpbGUgPSBOVUxMLCBsb2NhdGlvbiA9ICIuL2RhdGEvcHJvY2Vzc2VkLyIpIHsNCiAgICBpZmVsc2UoIWRpci5leGlzdHMoImRhdGEiKSwgZGlyLmNyZWF0ZSgiZGF0YSIpLCBGQUxTRSkNCiAgICBpZmVsc2UoIWRpci5leGlzdHMoImRhdGEvcHJvY2Vzc2VkIiksIGRpci5jcmVhdGUoImRhdGEvcHJvY2Vzc2VkIiksIEZBTFNFKQ0KICAgIGlmIChpcy5udWxsKGZpbGUpKQ0KICAgICAgICBmaWxlID0gZGVwYXJzZShzdWJzdGl0dXRlKHgpKQ0KICAgIGRhdGVuYW1lIDwtIHN1YnN0cihnc3ViKCJbOi1dIiwgIiIsIFN5cy50aW1lKCkpLCAxLCA4KQ0KICAgIHRvdGFsbmFtZSA8LSBwYXN0ZShsb2NhdGlvbiwgZGF0ZW5hbWUsIGZpbGUsICIucmRhIiwgc2VwID0gIiIpDQogICAgc2F2ZSh4LCBmaWxlID0gdG90YWxuYW1lKSAgI25lZWQgdG8gZml4IGlmIGZpbGUgaXMgcmVsb2FkZWQgYXMgaW5wdXQgbmFtZSwgbm90IGFzIHguIA0KfQ0KDQpmbG9hZCA8LSBmdW5jdGlvbihmaWxlbmFtZSkgew0KICAgIGxvYWQoZmlsZW5hbWUpDQogICAgZ2V0KGxzKClbbHMoKSAhPSAiZmlsZW5hbWUiXSkNCn0NCg0KZnNob3dkZiA8LSBmdW5jdGlvbih4LCAuLi4pIHsNCiAgICBrbml0cjo6a2FibGUoeCwgZGlnaXRzID0gMiwgImh0bWwiLCAuLi4pICU+JQ0KICAgICAgICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpKSAlPiUNCiAgICAgICAga2FibGVFeHRyYTo6c2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikNCn0NCg0KY29sb3JpemUgPC0gZnVuY3Rpb24oeCwgY29sb3IpIHsNCiAgICBzcHJpbnRmKCI8c3BhbiBzdHlsZT0nY29sb3I6ICVzOyc+JXM8L3NwYW4+IiwgY29sb3IsIHgpDQp9DQpgYGANCg0KDQoNCmBgYHtyfQ0KcGFja2FnZXMgPSBjKCJSU2llbmEiLCAiZGV2dG9vbHMiLCAiaWdyYXBoIikNCmZwYWNrYWdlLmNoZWNrKHBhY2thZ2VzKQ0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoJ0pvY2hlbVRvbHNtYS9Sc2llbmFUd29TdGVwJywgYnVpbGRfdmlnbmV0dGVzPVRSVUUpDQpwYWNrYWdlcyA9IGMoIlJzaWVuYVR3b1N0ZXAiKQ0KZnBhY2thZ2UuY2hlY2socGFja2FnZXMpDQpgYGANCg0KTkVFRCBEQVRBIC0gdXNlIGJ1aWxkIGluIGRhdGFzZXRzIGZyb20gUlNJRU5OQSANCj9zNTAxDQpJcyBhZGphY2VuY3kgbWF0cml4IGZvciBuZXR3b3JrIHR5cGUgMS4gR29hbDogRm9sbG93IHN0ZXBzIGluIDcuMSBmb3IgZGlmZmVyZW50IGRhdGE6DQoNCiMgU3RlcCAxLiBEZWZpbmUgZGF0YQ0KRGVwZW5kZW50IHZhcmlhYmxlOiB0aWVzIA0KDQoNCmBgYHtyfQ0KczUwMSAjbmV0d29yayBhdCB0aW1lcG9pbnQgMQ0KczUwMiAjbmV0d29yayBhdCB0aW1lcG9pbnQgMg0KYGBgDQoNCg0KSW5zcGVjdCBuZXR3b3Jrcy4gUmVtb3ZlIE5BcywgbWFrZSBzdXJlIGRpYWdvbmFsLiBOZWVkIHRvIHNlZSBiaW5hcnkgKG5vdCB3ZWlnaHRlZCkNCmBgYHtyfQ0KDQpgYGANCg0KDQpQdXQgbmV0d29ya3MgaW4gYW4gYXJyYXkNCmBgYHtyfQ0KDQpkaW0oczUwMSkgI3NheXMgNTB4NTA6IDUwIHJvd3MsIDUwIGNvbHVtbnMgaW4gZGF0YS4gDQoNCm5ldHMgPC0gYXJyYXkgKGRhdGEgPSBjKHM1MDEsIHM1MDIpLCBkaW0gPSBjKGRpbShzNTAxKSwgMikpICMNCmMoZGltKHM1MDEpLDIpDQoNCiMgZGltZW50aW9ucyBvZiBhcnJheSBhcmUgbnVtYmVyIG9mIGNvbHVtbnMgYW5kIG51bWJlciBvZiByb3dzIA0KYGBgDQogY291bGQgcmVwbGFjZSB0aGlzIHdpdGggZGF0YSBzZXQgZnJvbSBsYXN0IHdlZWsgDQogDQogDQpEZWZpbmUgZGVwZW5kZW50IC0gYW5kIGluZGVwZW5kZW50IC0gdmFyaWFibGUNCmBgYHtyfQ0KDQpuZXQgPC0gc2llbmFEZXBlbmRlbnQobmV0cykgI2RlcGVuZGVudCB2YXJpYWJsZSANCg0KICAjIGluZGVwZW5kZW50IHZhcmlhYmxlIC0gczUwYSAtIHdlIHdpbGwgdGFrZSBmaXJzdCB3YXkgDQphbGNvaG9sIDwtIHM1MGFbLDFdYWxjb2hvbA0KICMgZG9uJ3QgbmVlZCB3YXZlIDIgLSBqdXN0IG1vZGVsaW5nIGF0IGluZGVwZW5kZW50IHZhcmlhYmxlLCBpbmZsdWVuY2luZyBhbGwgbWluaXN0ZXBzIGJldHdlZW4gdGltZSAxIGFuZCB0aW1lIDIgDQphbGNvaG9sIA0KIA0KYWxjb2hvbCA8LSBjb0NvdmFyKGFsY29ob2wpIyBhdCBhY3RvciBsZXZlbCAtIG1lYW4gY2VudGVyZWQgLSBpcyBhIHRpbWUgY29uc3RhbnQgY29WYXJpYXRlIA0KYGBgDQoNCk5vdyBjb21iaW5lIGludG8gZGF0YXNldCAtIGlmIHVzZSBSc2llbmEsIG5lZWQgdGhpcy4gDQpgYGB7cn0NCm15ZGF0YSA8LSBzaWVuYURhdGFDcmVhdGUobmV0LCBhbGNvaG9sKQ0KDQpteWVmZiA8LSBnZXRFZmZlY3RzKG15ZGF0YSkgI2hhdmUgYSBsb29rIA0KbXllZmYNCmBgYA0KTm93IGNhbiBsb29rIGF0IG15ZWZmIC0gbG9vayBhdCBzdGFydGluZyB2YWx1ZXMgLSBoYXMgZGVuc2l0eSBvZiB0d28gbmV0d29ya3MsIHJlY2lwcm9jaXR5IA0KDQoNCldhbnQgbXVjaCBtb3JlIHN0YXRpc3RpY3MgZm9yIG1vZGVsLCB0aG91Z2ghISANCg0KIyBTdGVwIDI6IA0KQ2FuIHNlZSBhbGwgZWZmZWN0cyB0aGF0IGNvdWxkIGluY2x1ZGUgaW4gdGhlIGRhdGFzZXQuIFdoaWNoIGlzIGEgbG90LiBBbmQgdGhpcyBpcyBhIHNpbXBsZSBkYXRhc2V0LiBhbmQgeWVhaCwgaXRzIGh1Z2UuIEFsc28gY2FuIHNlZSB0aGF0IHRoZSB0eXBlIGRlcGVuZHMgb24gd2VpZ2h0IGZ1bmN0aW9uIChldmFsdWF0aW9uICgpLCBlbmRvd21lbnQgKCksIGFuZCBjcmVhdGlvbiAoKSkNCg0KRXhhbXBsZS4gSm9jaGVtIHdhbnRzIHRvIG1ha2UgdGllIHdpdGggSm9zLiBKb2NoZW0ncyBjb25zaWRlcmF0aW9uIHRvIG1ha2UgYSB0aWUgd2l0aCBKb3MgY291bGQgYmUgZGlmZmVyZW50IHRoYW4gY29uc2lkZXJhdGlvbiB0byBtYWludGFpbiBhIHRpZSwgY291bGQgYmUgZGlmZmVyZW50IHRoYXQgZGVjaXN0aW9ucyB0byBicmVhayBhIHRpZS4gQ2FuJ3QgZXN0aW1hdGUgYWxsIHRocmVlLiBFdmFsdXRpb246IG1lY2hhbmlzbXMgdGhlIHNhbWUgZm9yIG1ha2luZyBhcyBicmVha2luZywgZW5kb3dtZW50ID0gbWFpbnRhaW5pbmcsIGNyZWF0aW9uID0gaWYgdGhlcmUgYXJlIG5vbmUgdGhlbiB3aGF0IGlzIHRoZSBjb3N0LiANCg0KSW4gdGhpcyBjb3Vyc2U6IGp1c3QgdXNlIGV2YWx1YXRpb24gZnVuY3Rpb24uIEFzc3VtZSBtZWNoYW5pc21zIGFuZCBmdW5jdGlvbnMgdG8gbWFrZS9icmVhayB0aWVzIGFyZSBzaW1pbGFyLiBpbmNsdWRlIGRlZ3JlZSBmb3IgZXZhbHVhdGlvbi4gQnV0IHdoYXQgYXJlIGFsbCB0aGVzZSBlZmZlY3RzPyANCi0gICAgc2hvdWxkIGJlIGFibGUgdG8gY2FsY3VsYXRlIHN0YXRpc3RpYyBmb3IgZWFjaCBlZmZlY3QgZm9yIGFuIGVnbyBpbiBhIG5ldHdvcmsuLi4gTWF0aGVtYXRpY2FsIGZvcm11bGEgaW4gY2hhcHRlciAxMi4gDQoNCg0KYGBge3J9DQplZmZlY3RzRG9jdW1lbnRhdGlvbihteWVmZikNCmBgYA0KDQoNCk1ha2Ugc3VyZSB0byB1bmRlcnN0YW5kIG91dCBkZWdyZWUgYW5kIHJlY2lwcm9jaXR5IGVmZmVjdHMgLSBzdGF0aXN0aWNzIC0gd2lsbCBwbGF5IGFyb3VuZCB3aXRoIHRoaXMgbmV4dCB3ZWVrLiBOZWVkIHRvIHRoaW5rIG9mIHRoZW9yeSBmb3Igd2hpY2ggc3RhdGlzdGljcyBhcmUgcmVsZXZhbnQuIA0KLSAgICBMb29rIGF0IGxpdGVyYXR1cmUgZm9yIHN0YXRpc3RpY3MsIHRoaW5rIGFib3V0IGl0LCBwbGF5IGFuZCBzZWUgaWYgZWZmZWN0cyBleGlzdHMgDQotICAgIGhvdyB3b3JrIGluIHJlYWxpdHk/IHByb3Bvc2UgaWRlYSwgd3JpdGUgbm90YXRpb24sIHNlZSBpZiBlZmZlY3QgZXhpc3RzIGluIG1hbnVhbCwgZXRjLiBMb3RzIG9mIG5vdGF0aW9uIGJlY2F1c2UgZXZlcnlvbmUgaXMgbG9va2luZyBmb3IgdGhlaXIgb3duIGVmZmVjdHMuIA0KLSAgICBuZWVkIHRvIGluY2x1ZGUgbW9yZSBlZmZlY3RzIGlmIHdoYXQgdG8uIA0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KDQojIFN0ZXAgMzogTG9vayBhdCBpbnRpYWwgZGF0YQ0KLSAgICBnb29kIGZvciBkZWNpZGluZyBzdGF0aXN0aWNzIHRvIHVzZS4gDQpgYGB7cn0NCnByaW50MDFSZXBvcnQobXlkYXRhKQ0KDQojIGdpdmVzIGluaXRpYWwgZGVzY3JpcHRpb24gb2YgZGF0YSANCiMgcmVhZGluZyBuZXR3b3JrIHZhcmlhYmxlcyAsIGNvdmFyaWF0ZXMsIGRlbnNpdHkgbWVhc3VyZXMvY2hhbmdlcyBpbiBuZXR3b3JrcywgdGllIGNoYW5nZXMgYmV0d2VlbiBzdWJzZXF1ZW50IG9ic2VydmF0aW9ucy4uLiBjYWxjdWxhdGUgaG93IG11Y2ggbmV0d29ya3MgY2hhbmdlZCBvdmVyIHRpbWUuIA0KIyBkb250IHVzZSBiYWxhbmNlIGNhbGN1bGF0aW9uIA0KYGBgDQoNCiMgU3RlcCA0OiBBZGQgZWZmZWN0cw0KDQpgYGB7cn0NCm15ZWZmIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmLCBpc29sYXRlTmV0LCBpblBvcCwgb3V0QWN0KQ0KDQojb3V0QWN0IC0gb3V0ZGVncmVlIHJlbGF0ZWQgYWN0aXZpdHkgDQpgYGANCg0Kb3V0QWN0DQotIGxvb2sgYXQgdGhlIG51bWJlciBvZiB0aW1lcyBJIGhhdmUgYW5kIHNxdWFyZSB0aGF0OiBlc3BlY2lhbGx5IHRoZSBwZW9wbGUgdGhhdCBoYXZlIGEgbG90IG9mIHRpZXMgd2lsbCBzZW5kIGEgbG90IG9mIHRpZXMuIA0KLSBldmFsdWF0aW9uIGZ1bmN0aW9uIG9mIHRpZTEgMCB0aWVzLCBhbmQgdGllMSA0IHRpZXMgLSB0aGVuIGF0IHQyIHBlb3BsZSB3aG8gaGF2ZSB0aWVzIGFyZSBtb3JlIGxpa2VseSB0byBzZW5kIG1vcmUgdGllcyANCg0KV2Uga25vdyB0aWUgZGlzdHJpYnV0aW9ucyBhcmUgc2tld2VkLCBzb21lIHBlb3BsZSBzZW5kIGEgbG90IG9mIHRpZXMgYW5kIG90aGVycyBkb250LiANCg0KaW5Qb3A6IGluIGRlZ3JlZSBhY3Rpdml0eTogcGVvcGxlIHdobyByZXNlaXZlIGEgbG90IG9mIGluLWRlZ3JlZXMgc2VuZCBhIGxvdCBvZiBvdXQtZGVncmVlcyANCg0KaXNvbGF0ZU5ldDogcGVvcGxlIHdpdGhvdXQgYSBsb3Qgb2YgaW5kZWdyZWUgbmV0cy4gDQoNCg0KDQpDYW4gc2VlIHRoYXQgc3RhcnRpbmcgdmFsdWVzIGFyZSAwIC0tIGh5cG90aGVzaXMgdGVzdGluZyANCg0KIyBTdGVwIDU6IEVzdGltYXRpb24NCg0KYGBge3J9DQpteUFsZ29yaXRobSA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0IikNCg0KIyBkZWZpbmUgYWxnb3JpdGhtIHRoYXQgc2F5cyBob3cgSSB3YW50IHRvIGVzdGltYXRlIG15IG1vZGVsLiB3aWxsIHVzZSBkZWZhdWx0cy4gDQoNCmFuc00xIDwtIHNpZW5hMDcobXlBbGdvcml0aG0sIGRhdGEgPSBteWRhdGEsIGVmZmVjdHMgPSBteWVmZiwgcmV0dXJuRGVwcyA9IFRSVUUpDQojIHRoZW4gcnVuIGl0IHRvIHNlZSANCg0KYW5zTTENCg0KYGBgDQpOb3cgaGF2ZSBmaXJzdCBlc3RpbWF0ZWQgUnNpZW5hIG1vZGVsISANCg0KDQotIHNlZTpuZWdhdGl2ZSBvdXQgZGVncmVlIA0KLSAyLjQgcmVjaXByb2NpdHk6IGlzIGltcG9ydGFudCB0aGVuIGluIHRoaXMgbW9kZWwgDQotIGluZGVncmVlIHBvcHVsYXR5IGlzIHBvcHVsYXIgYnV0IG5vdCBzaWduaWZpY2FudC4uLiANCg0KaWYgc2lnbmlmaWNhbnQ6IG1vcmUgaW5kZWdyZWVzLSBtb3JlIGxpa2VseSB0byBzZW5kIGxhdGVyLiBwZW9wbGUgd2l0aCBtb3JlIG91dC1kZWdyZWVzIC0gbW9yZSBsaWtlbHkgdG8gc2VuZCBsZXNzIChuZWdhdGl2ZSkuIGlzb2xhdGUgbW9yZSBsaWtlbHkgdG8gYmUgYWxvbmUuIA0KDQoNCk5lZWQgdG8gdGhpbmsgb2YgbW9kZWwgdGhhdCBtYWtlcyBzZW5zZSBpbiB0aGlzDQoNCg0KYGBge3J9DQoNCmBgYA0KDQpSRVZJRVdJTkcgUlNJRU5BIE5PVw0KLSAgIG5lZ2F0aXZlIGRlZ3JlZSAtIGRlbnNpdHkgaXMgbGVzcyB0aGFuIC41IA0KLSAgIGludGVycHJldGF0aW9ucyANCi0gICBNYWlsaW5nIGxpc3QgZm9yIFRPTQ0KDQotICAgTm93OiByZS1yZWFkIGNoYXB0ZXIgMiBhbmQgY2hhcHRlciA1IA0KDQpBZnRlcm5vb246IHBsYXkgd2l0aCBlc3RpbWF0aW5nIG91ciBvd24gbW9kZWxzIA0KTmljZSB0byBkbyB3aXRoIG91ciBvd24gZGF0YSAtIGNvbGxhYm9yYXRpb24gbmV0d29ya3MuIA0KTG9naWMgb2YgUlNJRU5BOiB0b29rIGFjdG9yIG9yaWVudGVkIGFwcHJvYWNoIC0gd29ya3MgaWYgdGllcyBhcmUgZGlyZWN0ZWQuIGlmIHVuZGlyZWN0ZWQgbmV0d29yaywgbG9naWMgaXMgZGlmZmVyZW50OiB0aGUgYWN0b3IgZGVjaWRpbmcgb24gdW5kaXJlY3RlZCB0aWUgaXMgZGlmZmljdWx0LiBBZHZpc2U6IGZvciBub3cgdHJlYXQgYXMgdW5kaXJlY3RlZCAtIGFuZCB0aGVuIGV2YWx1YXRlIHRpZS4gDQp1bmRpcmVjdGVkIHRpZSBieSByZWFjaCBjb25zZW5zdXMsIGZvcmNlZCBpbnRvIGNvbmNlbnN1cywgZXRjIC0gcmVjaXByb2NpdHkgbWF0dGVycyBsZXNzIG5vdy4gDQoNCmBgYHtyfQ0KDQpgYGANCg0KIyBOb3cgcGxheSB3aXRoIGl0IA0KDQpgYGB7cn0NCg0KDQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCk5vdyAtIHJlZmVyZW5jaW5nIHdlYiBzY3JhcGluZyBzaXRlIA0KDQpgYGB7cn0NCmZjb2xuZXQgPC0gZnVuY3Rpb24oZGF0YSA9IHNjaG9sYXJzLCB1bml2ZXJzaXR5ID0gIlJVIiwgZGlzY2lwbGluZSA9ICJzb2Npb2xvZ3kiLCB3YXZlcyA9IGxpc3QoYygyMDE1LA0KICAgIDIwMTgpLCBjKDIwMTksIDIwMjMpKSwgdHlwZSA9IGMoImZpcnN0IikpIHsNCg0KICAgICMgc3RlcCAxDQogICAgZGVtb2dyYXBoaWNzIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgZGF0YSRkZW1vZ3JhcGhpY3MpDQogICAgZGVtb2dyYXBoaWNzIDwtIGRlbW9ncmFwaGljcyAlPiUNCiAgICAgICAgbXV0YXRlKFVuaXZlcnNpdGVpdDEuMjIgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDEuMjIsIGlzLm5hKFVuaXZlcnNpdGVpdDEuMjIpLCAiIiksIFVuaXZlcnNpdGVpdDIuMjIgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDIuMjIsDQogICAgICAgICAgICBpcy5uYShVbml2ZXJzaXRlaXQyLjIyKSwgIiIpLCBVbml2ZXJzaXRlaXQxLjI0ID0gcmVwbGFjZShVbml2ZXJzaXRlaXQxLjI0LCBpcy5uYShVbml2ZXJzaXRlaXQxLjI0KSwNCiAgICAgICAgICAgICIiKSwgVW5pdmVyc2l0ZWl0Mi4yNCA9IHJlcGxhY2UoVW5pdmVyc2l0ZWl0Mi4yNCwgaXMubmEoVW5pdmVyc2l0ZWl0Mi4yNCksICIiKSwgZGlzY2lwbGluZS4yMiA9IHJlcGxhY2UoZGlzY2lwbGluZS4yMiwNCiAgICAgICAgICAgIGlzLm5hKGRpc2NpcGxpbmUuMjIpLCAiIiksIGRpc2NpcGxpbmUuMjQgPSByZXBsYWNlKGRpc2NpcGxpbmUuMjQsIGlzLm5hKGRpc2NpcGxpbmUuMjQpLCAiIikpDQoNCiAgICBzYW1wbGUgPC0gd2hpY2goKGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQxLjIyICVpbiUgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQyLjIyICVpbiUNCiAgICAgICAgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQxLjI0ICVpbiUgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQyLjI0ICVpbiUNCiAgICAgICAgdW5pdmVyc2l0eSkgJiAoZGVtb2dyYXBoaWNzJGRpc2NpcGxpbmUuMjIgJWluJSBkaXNjaXBsaW5lIHwgZGVtb2dyYXBoaWNzJGRpc2NpcGxpbmUuMjQgJWluJSBkaXNjaXBsaW5lKSkNCg0KICAgIGRlbW9ncmFwaGljc19zb2MgPC0gZGVtb2dyYXBoaWNzW3NhbXBsZSwgXQ0KICAgIHNjaG9sYXJzX3NlbCA8LSBsYXBwbHkoc2Nob2xhcnMsICJbIiwgc2FtcGxlKQ0KDQogICAgIyBzdGVwIDINCiAgICBpZHMgPC0gZGVtb2dyYXBoaWNzX3NvYyRhdV9pZA0KICAgIG53YXZlcyA8LSBsZW5ndGgod2F2ZXMpDQogICAgbmV0cyA8LSBhcnJheSgwLCBkaW0gPSBjKG53YXZlcywgbGVuZ3RoKGlkcyksIGxlbmd0aChpZHMpKSwgZGltbmFtZXMgPSBsaXN0KHdhdmUgPSAxOm53YXZlcywgaWRzLA0KICAgICAgICBpZHMpKQ0KICAgIGRpbW5hbWVzKG5ldHMpDQoNCiAgICAjIHN0ZXAgMw0KICAgIGRmX3dvcmtzIDwtIHRpYmJsZSh3b3Jrc19pZCA9IHVubGlzdChsYXBwbHkoc2Nob2xhcnNfc2VsJHdvcmssIGZ1bmN0aW9uKGwpIGwkaWQpKSwgd29ya3NfYXV0aG9yID0gdW5saXN0KGxhcHBseShzY2hvbGFyc19zZWwkd29yaywNCiAgICAgICAgZnVuY3Rpb24obCkgbCRhdXRob3IpLCByZWN1cnNpdmUgPSBGQUxTRSksIHdvcmtzX3llYXIgPSB1bmxpc3QobGFwcGx5KHNjaG9sYXJzX3NlbCR3b3JrLCBmdW5jdGlvbihsKSBsJHB1YmxpY2F0aW9uX3llYXIpLA0KICAgICAgICByZWN1cnNpdmUgPSBGQUxTRSkpDQoNCiAgICBkZl93b3JrcyA8LSBkZl93b3Jrc1shZHVwbGljYXRlZChkZl93b3JrcyksIF0NCg0KICAgICMgc3RlcCA0DQogICAgaWYgKHR5cGUgPT0gImZpcnN0Iikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ28gPC0gZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZFsxXQ0KICAgICAgICAgICAgICAgIGFsdGVycyA8LSBkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkWy0xXQ0KICAgICAgICAgICAgICAgIGlmIChzdW0oaWRzICVpbiUgZWdvKSA+IDAgJiBzdW0oaWRzICVpbiUgYWx0ZXJzKSA+IDApIHsNCiAgICAgICAgICAgICAgICAgIG5ldHNbaiwgd2hpY2goaWRzICVpbiUgZWdvKSwgd2hpY2goaWRzICVpbiUgYWx0ZXJzKV0gPC0gMQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIGlmICh0eXBlID09ICJsYXN0Iikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ28gPC0gcmV2KGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWQpWzFdDQogICAgICAgICAgICAgICAgYWx0ZXJzIDwtIHJldihkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkKVstMV0NCiAgICAgICAgICAgICAgICBpZiAoc3VtKGlkcyAlaW4lIGVnbykgPiAwICYgc3VtKGlkcyAlaW4lIGFsdGVycykgPiAwKSB7DQogICAgICAgICAgICAgICAgICBuZXRzW2osIHdoaWNoKGlkcyAlaW4lIGVnbyksIHdoaWNoKGlkcyAlaW4lIGFsdGVycyldIDwtIDENCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQoNCiAgICBpZiAodHlwZSA9PSAiYWxsIikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ29zIDwtIGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWQNCiAgICAgICAgICAgICAgICBpZiAoc3VtKGlkcyAlaW4lIGVnb3MpID4gMCkgew0KICAgICAgICAgICAgICAgICAgbmV0c1tqLCB3aGljaChpZHMgJWluJSBlZ29zKSwgd2hpY2goaWRzICVpbiUgZWdvcyldIDwtIDENCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQogICAgb3V0cHV0IDwtIGxpc3QoKQ0KICAgIG91dHB1dCRkYXRhIDwtIHNjaG9sYXJzX3NlbA0KICAgIG91dHB1dCRuZXRzIDwtIG5ldHMNCiAgICByZXR1cm4ob3V0cHV0KQ0KfQ0KYGBgDQoNCg0KRXhhbXBsZSBpbiBjbGFzcyBmcm9tIDEwIE9jdG9iZXINClNpZW5hIGRlcGVuZGVudCB2YXJpYWJsZSANCg0KYGBge3J9DQojIFN0ZXAgMTogbG9hZCBkYXRhDQpsaWJyYXJ5KFJTaWVuYSkNCj9zaWVuYURlcGVuZGVudCAjbG9vayBmb3IgZXhhbXBsZXMgLSBzY3JpcHQgZm9yIGhvdyB0byBydW4gc3R1ZmYgDQoNCg0KIyB0aGVuIGNoZWNrIHdhdmVzIGF2YWlsYWJsZQ0KczUwMSAjbmV0d29yayBhdCB0aW1lcG9pbnQgMQ0KczUwMiAjbmV0d29yayBhdCB0aW1lcG9pbnQgMg0KczUwMyAjbmV0d29yayBhdCB0aW1lcG9pbnQgDQoNCg0KbXluZXQxIDwtIHNpZW5hRGVwZW5kZW50KGFycmF5KGMoczUwMSwgczUwMiwgczUwMyksIGRpbT1jKDUwLCA1MCwgMykpKQ0KbXliZWggPC0gc2llbmFEZXBlbmRlbnQoczUwYSwgdHlwZT0iYmVoYXZpb3IiKQ0KDQogIyBsb29rIGZvciBzbW9raW5nIGFuZCBkcmlua2luZyBiZWhhdmlvcnMNCg0Kc21va2UgPC0gczUwcyAjdGltZSB2YXJ5aW5nIGNvdmFyaWF0ZS4gVGltZSBjb25zdGFudCBjb3ZhciAtIHZhckNvdmFyDQpzbW9rZSA8LSB2YXJDb3ZhcihzNTBzKQ0KDQpteWRhdGFfZXhhbXBsZSA8LSBzaWVuYURhdGFDcmVhdGUobXluZXQxLCBteWJlaCwgc21va2UpDQoNCg0KDQojIFN0ZXAgMjogbG9vayBhdCBkYXRhDQojcHJpbnQgcmVwb3J0IG9uIGRhdGEgcmVwb3J0cw0KDQpwcmludDAxUmVwb3J0KG15ZGF0YV9leGFtcGxlKQ0KDQoNCiMgU3RlcCAzOiBhZGQgZWZmZWN0cyANCm15ZWZmX2V4YW1wbGUgPC0gZ2V0RWZmZWN0cyhteWRhdGFfZXhhbXBsZSkNCm15ZWZmX2V4YW1wbGUNCg0KDQoNCm15ZWZmX2V4YW1wbGUgPC0gaW5jbHVkZUVmZmVjdHMobXllZmZfZXhhbXBsZSwgdW5lcXVhbFgsIG5hbWU9Im15bmV0MSIsIGludGVyYWN0aW9uMSA9ICJzbW9rZSIpDQpteWVmZl9leGFtcGxlDQoNCg0KI21ha2UgYWxnb3JpdGhtIHRvIHRoZW4gZXN0aW1hdGUgaXQNCmFsZ29fZXggPC0gc2llbmFBbGdvcml0aG1DcmVhdGUocHJvam5hbWUgPSAidGVzdF9leCIpDQphbnN3ZXJfZXggPC0gc2llbmEwNyhhbGdvX2V4LCBkYXRhPW15ZGF0YV9leGFtcGxlLCBlZmZlY3RzPW15ZWZmX2V4YW1wbGUsIHJldHVybkRlcHMgPSBUUlVFKQ0KDQphbnN3ZXJfZXgNCg0KDQojZG9lcyBpdCBjaGFuZ2UgaWYgZGVwZW5kZW50IFggDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAibXliZWgiKSAjbmFtZSA9IG5ldHdvcmsgZGVwZW5kZW50IHZhcmlhYmxlLCBpbnRlcmFjdGlvbiAxIGlzIGNvdmFyaWF0ZSAoc21va2luZykgLSBpZiBoYXZlIG11bHRpcGxlIG5ldG93cmtzLCB0aGVuIGNvdWxkIGhhdmUgdW5lcXVhbFggd2l0aCByZXNwZWN0IHRvIFguIFdlIHJlcGxhY2VkIHNtb2tlIHdpdGggbXkgYmVoYXZpb3IsIGFuZCByZXJ1biB0aGUgc2llbmEgbW9kZWwuIFRoaXMgaXMgYW4gYWxnb3JpdGhtLCBjYW4gYXNrIFJTaWVuYSB0byByZWZlcmVuY2UgcHJldmlvdXMgcmVzdWx0IHdpdGggJ3ByZXZhbnM9QU5TJyBhZnRlciByZXR1cm5EZXB0cyA9IFRSVUUNCmFuc3dlcl9leCA8LSBzaWVuYTA3KGFsZ29fZXgsIGRhdGE9bXlkYXRhX2V4YW1wbGUsIGVmZmVjdHM9bXllZmZfZXhhbXBsZSwgcmV0dXJuRGVwcyA9IFRSVUUpDQoNCmFuc3dlcl9leA0KIyBsb29raW5nIGF0IHJlc3VsdHMsIG15YmVoID0gZHJpbmtpbmcgLS0gZWdvIGxlc3MgbGlrZWx5IHRvIHNwZW5kIHRpbWUgd2l0aCBwZW9wbGUgd2hvIGRyaW5rIG1vcmUgb3IgbGVzcyB0aGFuIHRoZW0uIGVnbyBhbHNvIGxlc3MgbGlrZWx5IHRvIHNwZW5kIHRpbWUgd2l0aCBwZW9wbGUgd2hvIHNtb2tlIG1vcmUgb3IgbGVzcywgdG8gYSBsZXNzZXIgZXh0ZW50LiBDYW4gdXNlIHVuZXF1YWxYIGZvciBkZXBlbmRlbnQgdmFyaWFibGVzIGFuZCBjb3ZhcmlhdGVzLiBrZXkgZGlmZmVyZW5jZSBpbiBlc3RpbWF0aW9uIHByb2NlZHVyZTogDQojIHdlIGFyZSBhbHNvIG1vZGVsaW5nIGJlaGF2aW9yYWwgcmVzdWx0cyAtIGJlaGF2aW9yIGNoYW5naW5nIG92ZXIgdGltZSwgc2ltdWxhdGVkIHZpYSBtaW5pc3RlcCBsb2dpYyAob25lIHN0ZXAgdXAgb3IgZG93bikuIFRoZSBjcnVjaWFsIGRpZmZlcmVuY2U6IGR1cmluZyB0aGUgYWxnb3JpdGhtIA0KI0lmIGNvdW50IHN0YXRpc3RpYyBmb3Igc21va2UsIHRoZW4gYmV0d2VlbiB0aW1lIHBvaW50IDEgYW5kIDIgd2UgdXNlIHZhbHVlIGZyb20gdGltZXBvaW50IDEuIGJldHdlZW4gMi0zLCB1c2UgdGltZSBwb2ludCAyLiBCdXQgd2l0aGluIHRoZSB2YXJpYWJsZSwgdGhlIGVnbyBsZXZlbCBiZWhhdmlvciBpcyBjaGFuZ2luZy4gaXMgbm90IHVzaW5nIHRoZSB2YWx1ZSBhcyBvYnNlcnZlZCBhdCB0MSAtIGl0IGlzIHVzaW5nIHRoZSB2YWx1ZSBhcyBpcyBjdXJyZW50bHkgc2ltdWxhdGVkLiANCg0KDQoNCg0KDQojY291bGQgZXhjbHVkZSB2YXJpYWJsZSB0byB0aGVuIGluY2x1ZGUgYXMgY292YXJpYXRlIGVmZmVjdC4gDQoNCm15YmVoIDwtIHNpZW5hRGVwZW5kZW50KHM1MGEsIHR5cGU9ImJlaGF2aW9yIikgI2RlZmluZWQgYXMgZGVwZW5kZW50IHZhcmlhYmxlIA0KZHJpbmtpbmcgPC0gdmFyQ292YXIoczUwYSkgI2RlZmluZWQgYXMgY292YXJpYXRlIHZhcmlhYmxlIA0KDQojdXBkYXRlIGRhdGEgb2JqZWN0OiANCm15ZGF0YV9leGFtcGxlIDwtIHNpZW5hRGF0YUNyZWF0ZShteW5ldDEsIG15YmVoLCBkcmlua2luZywgc21va2UpDQoNCg0KI2FuZCBlZmZlY3RzIG9iamVjdDogDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAic21va2UiKQ0KDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAiZHJpbmtpbmciKQ0KDQphbGdvX2V4MiA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0X2V4IikNCg0KYW5zd2VyX2V4IDwtIHNpZW5hMDcoYWxnb19leDIsIGRhdGE9bXlkYXRhX2V4YW1wbGUsIGVmZmVjdHM9bXllZmZfZXhhbXBsZSwgcmV0dXJuRGVwcyA9IFRSVUUpDQphbnN3ZXJfZXgNCg0KI3RoZW4gdGhlIG5ldHdvcmsgZHluYW1pY3MgY2hhbmdlIA0KIyBpbnRlcnByZXRhdGlvbiBvZiB0aGUgcmF0ZSBjb25zdGFudCAtIHRoZSBhdmVyYWdlIGFtb3VudCBvZiBtaW5pc3RlcHMgZWFjaCBlZ28gaXMgbWFraW5nIGJldHdlZW4gdGhlIHR3byBvYnNlcnZhdGlvbnMNCg0KI2JlaGF2aW9yYWwgZHluYW1pY3M6IA0KIyB0aGUgcmF0ZSBjb25zdGFudDogdGhlIG51bWJlciBvZiBzdGVwcyBpbiB0aGUgYmVoYXZpb3JhbCBhc3BlY3QgDQoNCiNzdGF0aXN0aWMgZm9yIGxpbmVhciBzaGFwZSAtIGxpbmVhciBzaGFwZSBlZmZlY3QgLSB0aGUgdmFsdWUgb2YgdGhlICpjZW50ZXJlZCogYmVoYXZpb3JhbCB2YXJpYWJsZSAoYXZlcmFnZSBpbiB0aGUgdG90YWwgc2FtcGxlKS4gDQojIGlmIHBvc2l0aXZlLCB0cnkgdG8gaW5jcmVhc2UgYmVoYXZpb3IuIGVmZmVjdCBpcyB6MSAoemVkIHNjb3JlKSwgd2l0aCB0aGUgb3B0aW9ucyBvZiAxLCAwLCBvciAtMS4gYmVoYXZpb3IgaW5jcmVhc2VzIGJlY2F1c2UgcG9zaXRpdmVseSBldmFsdWF0ZXMgMSBtb3JlIHRoYW4gMCwgbW9yZSB0aGFuIC0xLiBBdCBzb21lIHBvaW50LCB0aG91Z2gsIGJlaGF2aW9yIHdpbGwgc3RvcCBpbmNyZWFzaW5nIC0gdGhhdCBpcyB6MiAoc3F1YXJlZCEpLiBzbywgcGFyYW1ldGVyIG1vZGVyYXRlcyBpdHNlbGYgd2l0aCB0aW1lPz8gDQoNCiMgdGhlc2UgYXJlIHRoZSBtaW5pbXVtIGVmZmVjdHMgdG8gaW5jbHVkZSwgYmVjYXVzZSBpdCBwcmVkaWN0cyBtZWFuIHZhbHVlIG9ic2VydmUgaW4gZGF0YXNldC4gMiBwYXJhbWV0ZXJzIC0gZXN0aW1hdGUgbWVhbiBiZWhhdmlvci4gYmFzZWQgb24gbW9kZWwgcmVzdWx0cywgd2hhdCBpcyB0aGUgbWVhbiB2YWx1ZS4gDQoNCiMgYmVoYXZpb3JhbCB2YXJpYWJsZXMgaW4gZGF0YXNldCAtIGV2ZXJ5dGhpbmcgb2JzZXJ2ZWQgdGhhdCBjaGFuZ2VzLiBleC4sIHBvc2l0aW9uIChmdW5jdGllKSwgY2l0YXRpb25zLCBpbnRlcmRpc2NpcGxpbmFyaXR5IHNjb3JlLiBQcm9ibGVtOiBpcyB0aW1lIHdpbmRvdyBsYXJnZSBlbm91Z2h0IHRvIHNlZSBjaGFuZ2U/IGFuZCBvdmVyIHRpbWUsIGJlaGF2aW9yYWwgdmFyaWFibGUgaXMgb25seSBjaGFuZ2luZyAtIHdoaWNoIHRoZW4gbXVzdCBiZSBjYWxjdWxhdGVkIGFzIGNvbnRpbnVvdXMgZGVwZW5kZWQgdmFyaWFibGUuIA0KDQoNCmBgYA0KDQoNCg==